package com.itheima.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.constant.MessageConstant;
import com.itheima.entity.Result;
import com.itheima.pojo.CheckGroup;
import com.itheima.pojo.CheckItem;
import com.itheima.pojo.Member;
import com.itheima.pojo.Setmeal;
import com.itheima.service.*;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

//报表操作
@RestController
@RequestMapping("/report")
public class ReportController {

    @Reference
    private CheckGroupService checkGroupService;
    @Reference
    private CheckItemService checkItemService;
    @Reference
    private MemberService memberService;
    @Reference
    private OrderService orderService;
    @Reference
    private ReportService reportService;
    @Reference
    private SetmealService setmealService;

    //运营数据统计报表导出
    @RequestMapping("/exportBusinessReport")
    public Result exportBusinessReport(HttpServletRequest request, HttpServletResponse response) {
        try {
            Map<String, Object> data = reportService.getBusinessReportData();

            //取出返回的结果，准备将数据写到excel中去
            String reportDate = (String) data.get("reportDate");
            Integer todayNewMember = (Integer) data.get("todayNewMember");
            Integer totalMember = (Integer) data.get("totalMember");
            Integer thisWeekNewMember = (Integer) data.get("thisWeekNewMember");
            Integer thisMonthNewMember = (Integer) data.get("thisMonthNewMember");
            Integer todayOrderNumber = (Integer) data.get("todayOrderNumber");
            Integer thisWeekOrderNumber = (Integer) data.get("thisWeekOrderNumber");
            Integer thisMonthOrderNumber = (Integer) data.get("thisMonthOrderNumber");
            Integer todayVisitsNumber = (Integer) data.get("todayVisitsNumber");
            Integer thisWeekVisitsNumber = (Integer) data.get("thisWeekVisitsNumber");
            Integer thisMonthVisitsNumber = (Integer) data.get("thisMonthVisitsNumber");
            List<Map<String, Object>> hotSetmeal = (List<Map<String, Object>>) data.get("hotSetmeal");

            //获取excel模板文件的绝对路径(File.separator文件分割符，不同的操作系统分隔符不同)
            String filePath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_template.xlsx";

            //指定excel模板文件来创建新的表格（在内存中创建）
            XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream(new File(filePath)));
            //获取第一个工作表
            XSSFSheet sheet = excel.getSheetAt(0);
            //获取第3行第6列的单元格，将日期数据填入
            XSSFRow row = sheet.getRow(2);
            row.getCell(5).setCellValue(reportDate);
            //获取第5行第6列和第8列，分别将新增会员数和会员总数填入
            row = sheet.getRow(4);
            row.getCell(5).setCellValue(todayNewMember);
            row.getCell(7).setCellValue(totalMember);
            //获取第6行第6列和第8列，分别将本周新增会员数和本月新增会员数填入
            row = sheet.getRow(5);
            row.getCell(5).setCellValue(thisWeekNewMember);
            row.getCell(7).setCellValue(thisMonthNewMember);
            //获取第8行第6列和第8列，分别将本今日预约数和今日到诊数填入
            row = sheet.getRow(7);
            row.getCell(5).setCellValue(todayOrderNumber);
            row.getCell(7).setCellValue(todayVisitsNumber);
            //获取第9行第6列和第8列，分别将本周预约数和本周到诊数填入
            row = sheet.getRow(8);
            row.getCell(5).setCellValue(thisWeekOrderNumber);
            row.getCell(7).setCellValue(thisWeekVisitsNumber);
            //获取第10行第6列和第8列，分别将本周预约数和本周到诊数填入
            row = sheet.getRow(9);
            row.getCell(5).setCellValue(thisMonthOrderNumber);
            row.getCell(7).setCellValue(thisMonthVisitsNumber);
            //定位到13行，将热门套餐循环添加到表格中
            int rowNum = 12;
            for (Map<String, Object> map : hotSetmeal) {
                //分别获取热门套餐的名称，预约数量以及占比
                String name = (String) map.get("name");
                Long setmeal_count = (Long) map.get("setmeal_count");
                BigDecimal proportion = (BigDecimal) map.get("proportion");
                row = sheet.getRow(rowNum);
                row.getCell(4).setCellValue(name);
                row.getCell(5).setCellValue(setmeal_count);
                row.getCell(6).setCellValue(proportion.doubleValue());
                rowNum++;
            }

            //以浏览器为客户端，使用输出流下载excel文件
            ServletOutputStream out = response.getOutputStream();
            //设置响应头以指定excel类型写出
            response.setContentType("application/vnd.ms-excel");
            //设置响应头以指定以附件形式进行下载
            response.setHeader("content-Disposition", "attachment;filename=report.xlsx");
            //将文件写出
            excel.write(out);

            //刷新并关闭流
            out.flush();
            out.close();
            excel.close();

            //导出成功
            return new Result(true, MessageConstant.GET_BUSINESS_REPORT_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            //导出失败
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }

    //运营数据统计报表以PDF导出
    @RequestMapping("/exportBusinessReport4PDF")
    public Result exportBusinessReport4PDF(HttpServletRequest request, HttpServletResponse response) {
        try {
            Map<String, Object> data = reportService.getBusinessReportData();

            //取出返回的结果，准备将数据写到excel中去
            List<Map<String, Object>> hotSetmeal = (List<Map<String, Object>>) data.get("hotSetmeal");

            //动态获取模板文件绝对路径
            String jrxmlPath = request.getSession().getServletContext().getRealPath("template") + File.separator + "health_business3.jrxml";
            String jasperPath = request.getSession().getServletContext().getRealPath("template") + File.separator + "health_business3.jasper";

            //编译模板
            JasperCompileManager.compileReportToFile(jrxmlPath, jasperPath);

            //使用JavaBean数据源方式填充
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPath, data, new JRBeanCollectionDataSource(hotSetmeal));
            ServletOutputStream out = response.getOutputStream();
            response.setContentType("application/pdf");
            response.setHeader("content-disposition", "attachment;filename=report.pdf");

            //输出文件并关流
            JasperExportManager.exportReportToPdfStream(jasperPrint, out);
            out.flush();
            out.close();
            //导出成功
            return new Result(true, MessageConstant.GET_BUSINESS_REPORT_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            //导出失败
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }

    //会员数据统计报表以excel导出
    @RequestMapping("/exportMemberReport")
    public Result exportMemberReport(String ids, HttpServletRequest request, HttpServletResponse response) {

        try {
            //获取前台传入的数据，通过“，”拆分装入集合
            String[] arr = ids.split(",");
            //将会员ID分装到集合中
            List<Integer> list = new ArrayList<>();
            for (String s : arr) {
                int i = Integer.parseInt(s);
                list.add(i);
            }

            //获取excel模板文件的绝对路径(File.separator文件分割符，不同的操作系统分隔符不同)
            String filePath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_members.xlsx";
            //指定excel模板文件来创建新的表格（在内存中创建）
            XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream(new File(filePath)));
            //获取第一个工作表
            XSSFSheet sheet = excel.getSheetAt(0);

            //定位到6行，将信息 循环添加到表格中
            int rowNum = 5;

            //获取对集合应的id集合
            for (Integer i : list) {
                XSSFRow row = sheet.getRow(rowNum);

                //1.获取会员信息
                Member member = memberService.findById(i);

                String name = "";
                if (member.getName()==null){
                    name = "";
                }else{
                    name = member.getName();
                }

                String sex = "";
                if (member.getSex()==null){
                    sex = "不详";
                } else if (member.getSex().equals("2")) {
                    sex = "女";
                } else {
                    sex = "男";
                }

                String phoneNumber = "";
                if (member.getPhoneNumber()==null){
                    phoneNumber="";
                }else {
                    phoneNumber = member.getPhoneNumber();
                }
                //获取机构地址(暂无数据)

                //2.(套餐)根据会员ID获取获取套餐ID
                List<Integer> setmealIds = orderService.findSetmealIdByMemberId(i);
                List<String> setmealNames = new ArrayList<>();
                for (Integer setmealId : setmealIds) {
                    Setmeal setmeal = setmealService.findById(setmealId);
                    String setmealName = setmeal.getName();
                    setmealNames.add(setmealName);
                }


                //3.根据套餐ID查询检查组
                List<Integer> checkgroupIds = new ArrayList<>();
                for (Integer setmealId : setmealIds) {
                    checkgroupIds = setmealService.findCheckgroupIdsBySetmealId(setmealId);
                }

                List<String> checkgroupNames = new ArrayList<>();
                for (Integer checkgroupId : checkgroupIds) {
                    CheckGroup checkGroup = checkGroupService.findById(checkgroupId);
                    checkgroupNames.add(checkGroup.getName());
                }

                //4.根据检查组ID获获取所有的检查项
                List<String> checkItemNames = new ArrayList<>();
                for (Integer checkgroupId : checkgroupIds) {
                    List<Integer> checkItemIds = checkGroupService.findCheckItemIdsByCheckGroupId(checkgroupId);
                    for (Integer checkItemId : checkItemIds) {
                        CheckItem checkItem = checkItemService.findById(checkItemId);
                        checkItemNames.add(checkItem.getName());
                    }
                }

                //将获取的所有数据赋值到表格中
                row.getCell(0).setCellValue(name);
                row.getCell(1).setCellValue(sex);
                row.getCell(2).setCellValue(phoneNumber);
                row.getCell(3).setCellValue("合肥市瑶海区");
                row.getCell(4).setCellValue(setmealNames.toString());
                row.getCell(5).setCellValue(checkgroupNames.toString());
                row.getCell(6).setCellValue(checkItemNames.toString());

                rowNum++;
            }

            //以浏览器为客户端，使用输出流下载excel文件
            ServletOutputStream out = response.getOutputStream();
            //设置响应头以指定excel类型写出
            response.setContentType("application/vnd.ms-excel");
            //设置响应头以指定以附件形式进行下载
            response.setHeader("content-Disposition", "attachment;filename=Members_Report.xlsx");
            //将文件写出
            excel.write(out);

            //刷新并关闭流
            out.flush();
            out.close();
            excel.close();

            //导出成功
            return new Result(true, MessageConstant.GET_BUSINESS_REPORT_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }

    //获取运营统计数据
    @RequestMapping("/getBusinessReportData")
    public Result getBusinessReportData() {

        try {
            Map<String, Object> data = reportService.getBusinessReportData();
            return new Result(true, MessageConstant.GET_BUSINESS_REPORT_SUCCESS, data);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }

        //模拟数据测试
        /*data.put("reportDate","2020.10.31");
        data.put("todayNewMember",46);
        data.put("totalMember",3000);
        data.put("thisWeekNewMember",100);
        data.put("thisMonthNewMember",250);
        data.put("todayOrderNumber",8);
        data.put("todayVisitsNumber",10);
        data.put("thisWeekOrderNumber",40);
        data.put("thisWeekVisitsNumber",89);
        data.put("thisMonthOrderNumber",210);
        data.put("thisMonthVisitsNumber",299);*/

        /*Map map1 = new HashMap();
        map1.put("name","粉红珍爱(女)升级TM12项筛查体检套餐");
        map1.put("setmeal_count",4);
        map1.put("proportion",0.636);

        Map map2 = new HashMap();
        map2.put("name","阳光爸妈升级肿瘤12项筛查（男女单人）体检套餐");
        map2.put("setmeal_count",6);
        map2.put("proportion",0.222);

        List<Map<String,Object>> hotSetmeal = new ArrayList();
        hotSetmeal.add(map1);
        hotSetmeal.add(map2);
        data.put("hotSetmeal",hotSetmeal);*/

        /*return new Result(true,MessageConstant.GET_BUSINESS_REPORT_SUCCESS,data);*/
    }

    //获取会员数量折线数据
    @RequestMapping("/getMemberReport")
    public Result getMemberReport() {
        Map<String, Object> map = new HashMap<>();
        List<String> months = new ArrayList<>();
        //获取日历对象，模拟时间为当前时间,计算并获取当前时间的前一年的时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -12);
        //定义日期格式最好不要在循环中new对象，防止在循环中多次创建对象避免占用内存
        //而且不要在全局变量中将SimpleDateFormat与static一起使用，因为前者是线程不安全的类型，要改用DateUtils
        SimpleDateFormat format = new SimpleDateFormat("yyyy.MM");
        for (int i = 0; i < 12; i++) {
            //获取当前时间往后退一个月的日期
            calendar.add(Calendar.MONTH, 1);
            Date date = calendar.getTime();
            //最好不要在循环中new对象
            //months.add(new SimpleDateFormat("yyyy.MM").format(date));
            months.add(format.format(date));
        }
        map.put("months", months);

        //通过月份查找会员人数
        List<Integer> memberCount = memberService.findMemberCountByMonths(months);
        map.put("memberCount", memberCount);

        return new Result(true, MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS, map);
    }

    //获取复选框选中会员的基本信息以及预约信息
    @RequestMapping("/getMembersReportData")
    public Result getMembersReportData() {
        //模拟测试数据
        List<Map<String, Object>> data = new ArrayList<>();

        Map map1 = new HashMap();
        map1.put("name", "李宇航");
        map1.put("sex", "男");
        map1.put("phoneNumber", "18012345678");

        Map map2 = new HashMap();
        map2.put("name", "赵亚男");
        map2.put("sex", "男");
        map2.put("phoneNumber", "18000000000");

        data.add(map1);
        data.add(map2);

        return new Result(true, MessageConstant.GET_BUSINESS_REPORT_SUCCESS, data);
    }

    //获取套餐数据饼形图
    @RequestMapping("/getSetmealReport")
    public Result getSetmealReport() {
        //根据json返回数据格式可知，data需要用map集合
        Map<String, Object> data = new HashMap<>();

        /*List<String> setmealNames = new ArrayList<>();
        //模拟套餐数据
        setmealNames.add("李宇航");
        setmealNames.add("赵亚男");
        data.put("setmealNames",setmealNames);*/

        try {
            List<Map<String, Object>> setmealCount = setmealService.findSetmealCount();

            List<String> setmealNames = new ArrayList<>();
            for (Map<String, Object> map : setmealCount) {
                //获取套餐名称,并放入集合中
                setmealNames.add((String) map.get("name"));
            }
            //将套餐名称放入map集合
            data.put("setmealNames", setmealNames);

            //模拟套餐
            /*Map map1 = new HashMap();
            map1.put("name","李宇航");
            map1.put("value","200");

            Map map2 = new HashMap();
            map2.put("name","赵亚男");
            map2.put("value","300");
            //将集合放到list数组中
            setmealCount.add(map1);
            setmealCount.add(map2);*/

            //将套餐详细信息放入map集合中
            data.put("setmealCount", setmealCount);
            //查询成功，返回结果并将数据返回
            return new Result(true, MessageConstant.GET_SETMEAL_COUNT_REPORT_SUCCESS, data);
        } catch (Exception e) {
            e.printStackTrace();
            //查询失败
            return new Result(false, MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL);
        }
    }

}
